/*
 * Copyright (c) 2023-2024 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.common.util.lang;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import lombok.experimental.UtilityClass;

/**
 * BeanUtils
 *
 * @author zeng
 */
@UtilityClass
public class BeanUtils {
  /**
   * 转义bean中所有属性为字符串的
   *
   * @param bean {@link Object}
   */
  public static void beanAttributeValueEscapeXml(Object bean) {
    try {
      if (bean != null) {
        // 获取所有的字段包括public,private,protected,private
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field f : fields) {
          if ("java.lang.String".equals(f.getType().getName())) {
            // 获取字段名
            String key = f.getName();
            Object value = getFieldValue(bean, key);

            if (value == null) {
              continue;
            }
            setFieldValue(bean, key, escapeXml(value.toString()));
          }
        }
      }
    } catch (Exception e) {
      throw ExceptionUtils.mpe(e);
    }
  }

  /**
   * 转义xml中的特殊字符
   *
   * @param input {@link String}
   * @return {@link String}
   */
  public static String escapeXml(String input) {
    if (input == null) {
      return "";
    }
    return input
        .replace("&", "&amp;")
        .replace("<", "&lt;")
        .replace(">", "&gt;")
        .replace("\"", "&quot;")
        .replace("'", "&apos;");
  }

  /**
   * bean 中所有属性为字符串的进行\n\t\s处理
   *
   * @param bean {@link Object}
   */
  public static void beanAttributeValueReplaceBlank(Object bean) {
    try {
      if (bean != null) {
        // 获取所有的字段包括public,private,protected,private
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field f : fields) {
          if ("java.lang.String".equals(f.getType().getName())) {
            // 获取字段名
            String key = f.getName();
            Object value = getFieldValue(bean, key);
            if (value == null) {
              continue;
            }
            setFieldValue(bean, key, StringUtils.replaceBlank(value.toString()));
          }
        }
      }
    } catch (Exception e) {
      throw ExceptionUtils.mpe(e);
    }
  }

  /**
   * 去掉bean中所有属性为字符串的前后空格
   *
   * @param bean {@link Object}
   */
  public static void beanAttributeValueTrim(Object bean) {
    try {
      if (bean != null) {
        // 获取所有的字段包括public,private,protected,private
        Field[] fields = bean.getClass().getDeclaredFields();
        for (Field f : fields) {
          if ("java.lang.String".equals(f.getType().getName())) {
            // 获取字段名
            String key = f.getName();
            Object value = getFieldValue(bean, key);

            if (value == null) {
              continue;
            }
            setFieldValue(bean, key, value.toString().trim());
          }
        }
      }
    } catch (Exception e) {
      throw ExceptionUtils.mpe(e);
    }
  }

  /**
   * 利用反射通过get方法获取bean中字段fieldName的值
   *
   * @param bean {@link Object}
   * @param fieldName {@link String}
   * @return {@link Object}
   * @throws Exception Exception
   */
  private static Object getFieldValue(Object bean, String fieldName) throws Exception {
    String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

    Object object;
    Method method;

    @SuppressWarnings("rawtypes")
    Class[] classArr = new Class[0];
    method = bean.getClass().getMethod(methodName, classArr);
    object = method.invoke(bean);

    return object;
  }

  /**
   * 利用发射调用bean.set方法将value设置到字段
   *
   * @param bean {@link Object}
   * @param fieldName {@link String}
   * @param value {@link Object}
   * @throws Exception Exception
   */
  private static void setFieldValue(Object bean, String fieldName, Object value) throws Exception {
    String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    // 利用发射调用bean.set方法将value设置到字段
    Class<?>[] classArr = new Class[1];
    classArr[0] = "java.lang.String".getClass();
    Method method = bean.getClass().getMethod(methodName, classArr);
    method.invoke(bean, value);
  }
}
